package com.study.cloud.gateway.core.filter.loadBalance;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.study.cloud.gateway.common.enums.ResponseCode;
import com.study.cloud.gateway.common.exception.InstanceNotFoundException;
import com.study.cloud.gateway.common.rule.DynamicConfigManager;
import com.study.cloud.gateway.common.rule.ServiceInstance;
import com.study.cloud.gateway.core.context.GatewayContext;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author wangwancheng
 * @create 2025/7/20 17:22
 */
@Slf4j
public class RoundLoadBalanceRule implements IGatewayLoadBalanceRule {

    private AtomicInteger position = new AtomicInteger(1);

    private final String uniqueId;

    public RoundLoadBalanceRule(String uniqueId) {
        this.uniqueId = uniqueId;
    }

    private static ConcurrentHashMap<String, RoundLoadBalanceRule>  serviceMap = new ConcurrentHashMap<>();

    public static RoundLoadBalanceRule getInstance(String serviceId) {
        RoundLoadBalanceRule randomLoadBalanceRule = serviceMap.get(serviceId);
        if (randomLoadBalanceRule == null){
            randomLoadBalanceRule = new RoundLoadBalanceRule(serviceId);
            serviceMap.putIfAbsent(serviceId, randomLoadBalanceRule);
        }
        return randomLoadBalanceRule;
    }
    @Override
    public ServiceInstance choose(GatewayContext gatewayContext) {
        return choose(gatewayContext.getUniqueId());
    }

    @Override
    public ServiceInstance choose(String uniqueId) {
        Set<ServiceInstance> serviceInstances = DynamicConfigManager.getInstance().getServiceInstances(uniqueId);
        if (CollectionUtils.isEmpty(serviceInstances)){
            log.error("not found serviceInstances");
            throw new InstanceNotFoundException(ResponseCode.SERVICE_INSTANCE_NOT_FOUND);
        }
        List<ServiceInstance> instances = new ArrayList<>(serviceInstances);
        int post = this.position.incrementAndGet() + instances.size();
        return instances.get(post % instances.size());
    }
}
